package com.totoro.mongo.service;

import com.mongodb.*;
import com.totoro.mongo.exception.NotFoundDataException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.Date;

@Service
public class AccountService {
    private static final Logger logger = LoggerFactory.getLogger(AccountService.class);
    @Resource
    MongoTemplate mongoTemplate;

    private static final String TABLE_USER = "T_User";
    private static final String TABLE_ACCOUNT = "T_Account";
    private static final String TABLE_DISABLE_WECHAT_ACCOUNT = "T_Disable_Wechat_Account";
    private static final String TABLE_DEAL_SCHEDULE = "T_Deal_Schedule";
    private static final String TABLE_DEAL_LOG = "T_Deal_Log"; //记录删除的数据的表

    private static final String WECHAT_ACCOUNT = "WECHAT";

    public void collectData(String skip, int limit) throws NotFoundDataException, Exception {
        int i = 0;
        try {
            DBCursor cursor = findDisableUser(skip, limit);

            if (!cursor.hasNext()) {
                throw new NotFoundDataException("没有不符合条件的异常数据！");
            }

            while (cursor.hasNext()) {
                i++;
                DBObject user = cursor.next();
                String userId = (String) user.get("_id");
                //查询Account
                DBCursor accountCursor = findWechatAccount(userId);

                while (accountCursor.hasNext()) {
                    DBObject account = accountCursor.next();
                    String name = (String) account.get("name");
                    saveWechatMulAccount(name);
                }

                skip = userId;

            }
        } catch (Exception e) {
            logger.error("执行查询DISABLE状态的User异常！已执行记录数：{}", i, e);
            throw e;
        }

        //保存本次执行的最后id
        saveQuerySkipSchedule(skip);

    }

    public void dealData(String skip, int limit) throws NotFoundDataException, Exception {
        DBCursor cursor = getErrorData(skip, limit);
        if (!cursor.hasNext()) {
            throw new NotFoundDataException("没有未处理的错误数据！");
        }

        try {
            dealErrorData(cursor);
        } catch (Exception e) {
            logger.error("处理错误数据异常！", e);
            throw e;
        }


    }

    /**
     * 分页查询DISABLE状态的User
     *
     * @param skip
     * @param limit
     */
    public DBCursor findDisableUser(String skip, int limit) {
        BasicDBObject status_disable_query = new BasicDBObject();
//        status_disable_query.put("status","DISABLE") ;
//        status_disable_query.put("_id", new BasicDBObject("$gt",skip)) ;
        status_disable_query.append("status", "DISABLE")
                .append("_id", new BasicDBObject().append(QueryOperators.GT, skip));

        DBCursor cursor = mongoTemplate.getCollection(TABLE_USER).find(status_disable_query).limit(limit);
        return cursor;
    }


    /**
     * 查询状态为DISABLE的user对应的Account
     *
     * @param user
     */
    public DBCursor findWechatAccount(String user) {
        DBObject wechat_account = new BasicDBObject();
        wechat_account.put("user", user);
        wechat_account.put("accountType", WECHAT_ACCOUNT);

        DBCursor cursor = mongoTemplate.getCollection(TABLE_ACCOUNT).find(wechat_account);

        return cursor;
    }

    /**
     * 判断name是否重复（微信名重复的bug导致）
     *
     * @param wechatName
     * @return
     */
    public boolean judgeWechatMulAccount(String wechatName) {
        DBObject count_query = new BasicDBObject();
        count_query.put("name", wechatName);
        count_query.put("accountType", WECHAT_ACCOUNT);
        long count = mongoTemplate.getCollection(TABLE_ACCOUNT).count(count_query);

        return count > 1;
    }


    /**
     * 保存状态为DISABLE,账号类型为WECHAT的Account记录(包括那条正常的记录)
     *
     * @param account
     */
    public void saveDisableWechatAccount(DBObject account) {
        boolean tableExists = mongoTemplate.collectionExists(TABLE_DISABLE_WECHAT_ACCOUNT);
        if (!tableExists)
            mongoTemplate.createCollection(TABLE_DISABLE_WECHAT_ACCOUNT);

        mongoTemplate.getCollection(TABLE_DISABLE_WECHAT_ACCOUNT).save(account);
    }

    public void saveWechatMulAccount(String wechatName) {
        if (judgeWechatMulAccount(wechatName)) {
            DBObject wechat_query = new BasicDBObject();
            wechat_query.put("name", wechatName);
            DBCursor cursor = mongoTemplate.getCollection(TABLE_ACCOUNT).find(wechat_query);
            while (cursor.hasNext()) {
                DBObject account = cursor.next();
                saveDisableWechatAccount(account);
            }
        }
    }


/************************************************************************************************************************/
    /**
     * 处理微信账号重复的数据。删掉状态为DISABLE的Account， 正常的Account对应的user表中isBindWeChat s字段设置为true，并刷新缓存
     *
     * @param skip
     * @param limit
     */
    public DBCursor getErrorData(String skip, int limit) {
        if (!mongoTemplate.collectionExists(TABLE_DISABLE_WECHAT_ACCOUNT))
            throw new IllegalStateException("错误数据对应的集合不存在！");
        BasicDBObject query_deal_data = new BasicDBObject().append("_id", new BasicDBObject().append(QueryOperators.GT, skip));
        DBCursor cursor = mongoTemplate.getCollection(TABLE_DISABLE_WECHAT_ACCOUNT).find(query_deal_data).limit(limit);
        return cursor;
    }

    public void dealErrorData(Cursor disableWechatAccount) {
        while (disableWechatAccount.hasNext()) {
            DBObject account = disableWechatAccount.next();

            String accountId = (String) account.get("_id");
            String userId = (String) account.get("user");

            DBObject query_user = new BasicDBObject();
            query_user.put("_id", userId);
            Cursor cursor = mongoTemplate.getCollection(TABLE_USER).find(query_user);
            if (cursor.hasNext()) {
                DBObject user = cursor.next();
                String status = (String) user.get("status");
                if (StringUtils.isEmpty(status))
                    continue;

                if (status.equals("DISABLE")) {
                    //删除该记录
                    dealErrorAccount(userId);
                } else {
                    //修改该user的isBindWeChat为true
                    updateWechatUser(userId);
                }
            }

            //保存处理的进度
            saveDealSkipSchedule(accountId);
        }
    }

    /**
     * 删除状态为Disable微信号重名的Account
     *
     * @param userId
     */
    public void dealErrorAccount(String userId) {
        DBObject remove_account = new BasicDBObject();
        remove_account.put("user", userId);

        DBCursor cursor = mongoTemplate.getCollection(TABLE_ACCOUNT).find(remove_account);
        //保存删除的数据
        saveDeleteLog(cursor.next());

        WriteResult removeResult = mongoTemplate.getCollection(TABLE_ACCOUNT).remove(remove_account);

    }

    /**
     * 修改状态正常微信号重名的User
     *
     * @param userId
     */
    public void updateWechatUser(String userId) {
        DBObject query_user = new BasicDBObject();
        query_user.put("_id", userId);

        DBObject update_user = new BasicDBObject().append("$set", new BasicDBObject("isBindWeChat", true));
//        update_user.put("isBindWeChat", true);

        mongoTemplate.getCollection(TABLE_USER).update(query_user, update_user);
    }

    /**
     * 记录处理进度
     * 查询DISABLE状态的User记录：
     * query_skip， query_limit, query_update_time
     * <p>
     * 处理重复Account的记录
     * deal_skip, deal_limit, deal_update_time
     * <p>
     * updateTime
     */
    public void createDealSchduleCollection() {
        if (!mongoTemplate.collectionExists(TABLE_DEAL_SCHEDULE))
            mongoTemplate.createCollection(TABLE_DEAL_SCHEDULE);

        //mongoTemplate.getCollection(TABLE_DEAL_SCHEDULE).findAndModify() ;
    }

    /**
     * 记录查询进度
     *
     * @param query_skip
     */
    public void saveQuerySkipSchedule(String query_skip) {
        if (StringUtils.isEmpty(query_skip)) {
            throw new IllegalArgumentException("保存的查询进度参数为空！" + query_skip);
        }
        saveSkipSchedule(query_skip, "query_skip", "query_update_time");
    }

    public String getQuerySkipSchedule() {

        return getSkipSchedule("query_skip");
    }

    /**
     * 记录处理数据的进度
     *
     * @param deal_skip
     */
    public void saveDealSkipSchedule(String deal_skip) {
        if (StringUtils.isEmpty(deal_skip)) {
            throw new IllegalArgumentException("保存的处理进度参数为空！" + deal_skip);
        }
        saveSkipSchedule(deal_skip, "deal_skip", "deal_update_time");
    }

    public String getDealSkipSchedule() {
        return getSkipSchedule("deal_skip");
    }

    private void saveSkipSchedule(String skip, String param, String timeParam) {
        createDealSchduleCollection();

        DBCollection collection = mongoTemplate.getCollection(TABLE_DEAL_SCHEDULE);

        DBObject query = new BasicDBObject();
        query.put("_id", "110");



        DBObject updateSkip = new BasicDBObject().append("$set", new BasicDBObject(param, skip));

        DBObject updateTime = new BasicDBObject().append("$set", new BasicDBObject(timeParam, new Date())) ;

        mongoTemplate.getCollection(TABLE_DEAL_SCHEDULE).update(query, updateSkip, true, false);
        mongoTemplate.getCollection(TABLE_DEAL_SCHEDULE).update(query, updateTime, true, false);
    }

    private String getSkipSchedule(String param) {
        DBObject query = new BasicDBObject();
        query.put("_id", "110");
        DBCursor cursor = mongoTemplate.getCollection(TABLE_DEAL_SCHEDULE).find(query);
        if (cursor.hasNext()) {
            String skip = (String) cursor.next().get(param);
            if (!StringUtils.isEmpty(skip))
                return skip;
        }
        return "000000000000000000000000"; //初始化最小的mongo的id值
    }

    /**
     * 删除一个数据保存下来以便日后恢复
     *
     * @param userId 删除的Account user字段值
     */
    private void saveDeleteLog(String userId) {
        DBObject remove_account = new BasicDBObject();
        remove_account.put("user", userId);
        DBCursor cursor = mongoTemplate.getCollection(TABLE_ACCOUNT).find(remove_account);
        saveDeleteLog(cursor.next());
    }

    private void saveDeleteLog(DBObject deleteObject) {
        if (deleteObject == null)
            return;

        if (!mongoTemplate.collectionExists(TABLE_DEAL_LOG))
            mongoTemplate.createCollection(TABLE_DEAL_LOG);

        try {
            mongoTemplate.getCollection(TABLE_DEAL_LOG).save(deleteObject);
        } catch (Exception e) {
            logger.error("保存删除的Account异常！Account数据为：" + deleteObject.toMap().toString());
        }
    }
}
